package com.jianqiao.delivery.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.jianqiao.delivery.pay.domain.initr2p.*;
import com.jianqiao.delivery.pay.service.R2PService;
import com.jianqiao.delivery.util.EncryptionUtils;
import com.nimbusds.jose.JOSEException;
import com.ruoyi.common.core.domain.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.net.ssl.*;
import java.io.*;
import java.security.*;
import javax.net.ssl.SSLContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

/**
 * author: cyx
 * create: 2024/11/22 17:41
 **/
@Slf4j
@Service
public class R2PServiceImpl implements R2PService {

    @Value("${visa.sandbox.url.R2P.initiate}")
    private String sandboxInitiateR2PUrl;

    @Value("${visa.sandbox.keyId}")
    private String sandboxKeyId;

    @Value("${visa.sandbox.username}")
    private String sandboxUsername;

    @Value("${visa.sandbox.password}")
    private String sandboxPassword;

    @Value("${visa.sandbox.KEY_STORE_PASSWORD}")
    private String KEY_STORE_PASSWORD;

    @Value("${visa.sandbox.PRIVATE_KEY_PASSWORD}")
    private String PRIVATE_KEY_PASSWORD;

    @Override
    public AjaxResult initiateR2P() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException, InvalidKeySpecException, JOSEException {
        String localTime = getTime();
        String random = "JQ" + random() + "EX";

        List<NationalIdentifiersEntity> nationalIdentifiersList = new ArrayList<>();
        NationalIdentifiersEntity nationalIdentifiersEntity = NationalIdentifiersEntity.builder().type("PASSPORT").value("350582200203163511").build();
        nationalIdentifiersList.add(nationalIdentifiersEntity);
        CreditorEntity creditorEntity = CreditorEntity.builder()
                .creditorAgentCountry("UA")
                .creditorAgentId("12379879797988")
                .creditorCountry("UA")
                .nationalIdentifiers(nationalIdentifiersList)
                .creditorId("BL1234567890")
                .creditorIdType("AGENT")
                .creditorMcc("1234")
                .creditorBusinessName("Jianqiao")
                .creditorAliasType("MOBL")
                .creditorAlias("+8615980048576")
                //选择P2P
//                .creditorFirstName("Chen")
//                .creditorLastName("Min")
                .build();

        PaymentRequestEntity paymentRequestEntity = PaymentRequestEntity.builder()
                .debtorAgentId("12379879797989")
                .debtorAgentCountry("UA")
                .debtorCountry("UA")
                .endToEndId("V")
                .requestedAmount(100)
                .requestedAmountCurrency("UAH")
                .debtorAliasType("MOBL")
                .debtorAlias("+8618005946608").build();
        List<PaymentRequestEntity> paymentRequestList = new ArrayList<>();
        paymentRequestList.add(paymentRequestEntity);

        SettlementOptionsEntity settlementOptionsEntity = SettlementOptionsEntity.builder()
                .settlementSystem("VISA_DIRECT")
                .primaryAccountNumber("4512890096447104")
                .build();
        List<SettlementOptionsEntity> settlementOptionsList = new ArrayList<>();
        settlementOptionsList.add(settlementOptionsEntity);

        ReferencesEntity referencesEntity = ReferencesEntity.builder()
                .referenceType("ORDERID")
                .referenceDate("2024-11-26")
                .referenceValue("1554002394").build();
        List<ReferencesEntity> referencesList = new ArrayList<>();
        referencesList.add(referencesEntity);
        RequestReasonEntity requestReasonEntity = RequestReasonEntity.builder().references(referencesList)
                .paymentPurpose("SVCS")
                .build();

        InitiateR2PEntity initiateR2PEntity = InitiateR2PEntity.builder()
                .creationDateTime("2023-09-17T09:30:47Z")
                .creditor(creditorEntity)
                .paymentRequests(paymentRequestList)
                .product("VD")
                .requestMessageId("GG9983636387737JH")
                .settlementOptions(settlementOptionsList)
                .useCase("P2P")
                .requestReason(requestReasonEntity).build();
        String encryptedPayload = EncryptionUtils.getEncryptedPayload(initiateR2PEntity, sandboxKeyId);

        // 创建HttpPost实例
        HttpPost httpPost = new HttpPost(sandboxInitiateR2PUrl);

        // 设置请求头
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("keyId", sandboxKeyId);
//        httpPost.setHeader("x-request-affinity", "RFP11664782648731jRko01");
        String authHeader = "Basic " + Base64.getEncoder().encodeToString((sandboxUsername + ":" + sandboxPassword).getBytes(StandardCharsets.UTF_8));
        httpPost.setHeader("Authorization", authHeader);

        // 设置请求体
        StringEntity entity = new StringEntity(encryptedPayload);
        httpPost.setEntity(entity);

        CloseableHttpClient httpClient = twoWaySSL();

        // 执行请求并获取响应
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {

            // 处理响应
            int statusCode = response.getStatusLine().getStatusCode();
            String responseBody = EntityUtils.toString(response.getEntity());
            String encData = JSONObject.parseObject(responseBody).getString("encData");

            //解码响应报文
            InitiateR2PResponseEntity decryptedPayload = EncryptionUtils.getDecryptedPayload(encData, InitiateR2PResponseEntity.class);
            System.out.println("Status Code: " + statusCode);
            System.out.println("Response Body: " + responseBody);
            System.out.println("decryptedPayload: " + decryptedPayload);
//        }
            log.info("成功发起创建R2P请求");
            return AjaxResult.success(decryptedPayload);
        }
    }

    @Override
    public void confirmR2P() {

    }

    @Override
    public void SSLCon() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
        CloseableHttpClient httpClient = twoWaySSL();

        HttpGet httpGet = new HttpGet("https://sandbox.api.visa.com/vdp/helloworld");
        String authHeader = "Basic " + Base64.getEncoder().encodeToString((sandboxUsername + ":" + sandboxPassword).getBytes(StandardCharsets.UTF_8));
        httpGet.setHeader("Authorization" ,authHeader);
        // 发送请求并获取响应
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            // 检查响应状态码
            System.out.println("Response Code: " + response.getStatusLine().getStatusCode());

            // 获取响应实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                // 读取响应内容
                try (InputStream content = entity.getContent();
                     BufferedReader reader = new BufferedReader(new InputStreamReader(content))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public CloseableHttpClient twoWaySSL() throws UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
        String KEY_STORE_PATH = "C:\\Users\\os\\Desktop\\VISA材料\\第三项目-默认\\myProject_keyAndCertBundle.jks";
//        String KEY_STORE_PASSWORD = "ptjq12345";
//        String PRIVATE_KEY_PASSWORD = "ptjq12345";

        // Load client certificate into key store
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray(),
                        PRIVATE_KEY_PASSWORD.toCharArray())
                .loadTrustMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray())
                .build();

        // Allow TLSv1.2 protocol only
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.2" }, null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());

        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslSocketFactory).build();

        return httpClient;
    }

    public String getTime() {
        // 获取当前时间的UTC表示
        ZonedDateTime utcNow = ZonedDateTime.now(java.time.ZoneId.of("UTC"));

        // 定义日期时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX");

        // 使用格式化器格式化日期时间
        String formattedDateTime = utcNow.format(formatter);

        // 注意：'X' 会自动处理时区偏移，包括生成 'Z' 表示 UTC
        System.out.println(formattedDateTime);
        return formattedDateTime;
    }

    public String random() {
        Random random = new Random();

        // 生成一个范围在10000000000到99999999999之间的随机数（11位纯数字）
        long randomNumber = 10000000 + random.nextInt(900000000);

        return String.valueOf(randomNumber);
    }

}
